﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SMSROUTER.Business;
using Settings;
using Utils;
using System.Data.SqlClient;
using System.Data;
using StorageManagement;

namespace SMSROUTER.StorageManagement
{
    public class SmsOutReportStorage : DictionaryStorage<int, SmsOutReportStruct>
    {
        /// <summary>
        /// Cập nhật trạng thái vào Database với những dữ liệu được lưu trong Storage
        /// </summary>
        public static void UpdateStatus()
        {
            ICollection<int> Keys = GetKeys();
            if (Keys.Count > 0)
            {
                Task[] task = new Task[Keys.Count];
                int i = 0;
                foreach (var key in Keys)
                {
                    task[i++] = Task.Factory.StartNew(tkey =>
                    {
                        List<SmsOutReportStruct> statisticList = DequeueElementData((int)tkey, AppSetting.BatchSize);
                        if (statisticList.Count < AppSetting.BatchSize)
                        {
                            DateTime now = DateTime.Now;
                            while ((statisticList.Count < AppSetting.BatchSize) && (DateTime.Now - now < TimeSpan.FromMilliseconds(AppSetting.UpdateDataDuration)))
                            {
                                statisticList.AddRange(DequeueElementData((int)tkey, AppSetting.BatchSize));
                            }
                        }
                        SmsOutReportStruct.BatchUpdate(DequeueElementData((int)tkey, AppSetting.BatchSize));
                    }, key);
                }
                Task.WaitAll(task);
            }
        }
        
        public static void UpdateStatusOnExit()
        {
            try
            {
                var source = DequeueAllElementData();
                SmsOutReportStruct.BatchUpdate(source);
                source.Clear();
            }
            catch (Exception ex)
            {
                Log.InsertLog(ex, null, AppSetting.WarningType.mt_error, null);
            }
        }

        /// <summary>
        /// Set lại Status cho các Item nằm trong Storage
        /// Nếu không tìm thấy Item thì thêm 1 Item mới vào Storage
        /// </summary>
        public static void SetStatus(int key, SmsOutWaiting sms, DateTime? reportTime, string status, int? threadId)
        {
            var report = SmsOutReportStorage.FindItem(key, item => item.SmsOutGUID == sms.SmsOutGUID);
            if (report == null)
                SmsOutReportStorage.EnqueueElementData(key, new SmsOutReportStruct(sms.RouterID, sms.SmsOutGUID, sms.CooperateGUID, sms.SentTime, reportTime, sms.RetryOnFailReqTimes, sms.RetryOnTimeOutReqTimes, status, threadId));
            else
                report.Status = status;
        }

        public static void EnqueuData(SmsOutReportStruct rpt)
        {
            if (rpt.RouterID.HasValue)
            {
                EnqueueElementData(rpt.RouterID.Value, rpt);
            }
        }
      
        public static void EnqueueXmlData()
        {
            try
            {
                string fileName = AppSetting.SmsOutReportBackupFileName;
                if (System.IO.File.Exists(fileName))
                {
                    SqlConnection conn = AppSetting.GetConnection();
                    if (conn.State == ConnectionState.Open)
                    {
                        List<SmsOutReportStruct> listRpt = Xml.ReadFromFileToList<SmsOutReportStruct>(fileName);
                        // Sau khi đọc file xml xong thì xóa file đi.
                        System.IO.File.Delete(fileName);

                        if (listRpt != null && listRpt.Count > 0)
                        {
                            foreach (SmsOutReportStruct item in listRpt)
                            {
                                EnqueuData(item);
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}